<?php

namespace App\Models;

use App\Admin\Attributes\HasModelUser;
use App\Models\Traits\HasUserAddress;
use App\Models\Traits\HasUserIdentity;
use App\Models\Traits\HasUserInvite;
use App\Models\Traits\HasUserOrder;
use App\Models\Traits\HasUserTeam;
use App\Models\Traits\HasUserWithdraw;
use App\Models\Traits\HasUserVipPurchase;
use App\Models\Traits\HasUserOrderCache;
use App\Models\Traits\HasUserOrderUnpaidCache;
use App\Models\Traits\HasUserOrderPendingCache;
use App\Models\Traits\HasUserOrderRunningCache;
use App\Models\Traits\HasUserOrderFinishedCache;
use App\Models\Traits\HasUserCache;
use App\Supports\BankCard\Traits\HasUserBankCard;
use App\Models\Traits\HasUserCart;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Storage;
use Laravel\Sanctum\HasApiTokens;
use Rainsens\Dinglog\Facades\Dinglog;
use Tymon\JWTAuth\Contracts\JWTSubject;
use App\Http\Controllers\Api\V1\Resources\NotificationResource;
use Illuminate\Database\Eloquent\Relations\HasOne;

class User extends Authenticatable implements JWTSubject
{
    use HasModelUser,
        Notifiable,
        HasUserInvite,
        HasUserIdentity,
        HasUserAddress,
        HasUserOrder,
        HasUserVipPurchase,
        HasFactory,
    	HasUserBankCard,
        HasUserCart,
        HasUserOrderCache,
        HasUserOrderUnpaidCache,
        HasUserOrderPendingCache,
        HasUserOrderRunningCache,
        HasUserOrderFinishedCache,
        HasUserCache;
        use Notifiable {notify as laravelNotify;}

    protected $fillable = [
    	'parent_id', 'is_parent', 'grade', 'invite_code',

	    'name', 'nickname', 'phone', 'signature', 'password', 'password_reset_sms_at', 'pay_code', 'avatar', 'gender', 'birthday',

	    'wm_openid', 'wm_session_key', 'wx_unionid', 'wx_openid',
	    'wx_nickname', 'wx_sex', 'wx_headimgurl', 'wx_country', 'wx_province', 'wx_city', 'wx_qrcode',
	    'alipay_user_id', 'alipay_nickname', 'alipay_avatar', 'alipay_province', 'alipay_city', 'alipay_user_no',
		'real_name', 'cert_number', 'bank_name' , 'bank_abbr',
	    'last_token', 'is_locked','vip_expired_at','dividend_brokerage','balance','is_new','address','linkdin_token'
    ];

    protected $hidden = [
	    'password',
	    'pay_code',
    ];

	protected $casts = [
		'is_mock' => 'boolean',
		'is_parent' => 'boolean',
        'is_gold_intern' => 'boolean',
        'is_gold_master' => 'boolean',
        'has_given_parent_cash' => 'boolean',
		'is_locked' => 'boolean',
	];

    protected $dates = [
        'password_reset_sms_at',
        'gold_wastes_order_at',
        'gold_wastes_subsidy_at',
    ];

	public function getJWTIdentifier()
	{
		return $this->getKey();
	}

	public function getJWTCustomClaims()
	{
		return [];
	}

	public function jsonNotificationTypes(): array
	{
		$types = [];
		foreach (config('site.notifications.types') as $type => $content) {
			$filter = config("site.notifications.types.{$type}.notification");
			$latest = $this->notifications()->where('type', $filter)->latest()->first();
			$unreadCount = $this->notifications()->where('type', $filter)->whereNull('read_at')->count();
			$types[] = [
				'type' => $type,
				'name' => $content['name'],
				'icon' => Storage::url($content['icon']),
				'latest' => $latest ? new NotificationResource($latest) : '',
				'unread_count' => $unreadCount,
			];
		}
		return ['data' => $types];
	}

	public function notify($instance)
	{
		if (method_exists($instance, 'toDatabase')) {
			$this->increment('notifications_count');
		}
		$this->laravelNotify($instance);
	}

    public function addresses(): HasMany
    {
        return $this->hasMany(Address::class);
    }

    public function orders()
    {
        return $this->hasMany(Order::class);
    }

    public function orderRefunds()
    {
        return $this->hasMany(OrderRefund::class);
    }

    public function blindBoxOrders()
    {
        return $this->hasMany(BlindBoxOrder::class);
    }
	
	public function freelance(): HasOne
	{
		return $this->hasOne(Freelance::class);
	}

    public function vipPurchases()
    {
        return $this->hasMany(VipPurchase::class, 'user_id', 'id');
    }

    public function accounts()
    {
        return $this->hasMany(Account::class, 'user_id', 'id');
    }

    public function brokerages()
    {
        return $this->hasMany(Brokerage::class, 'user_id', 'id');
    }
    
    public function welfareRecords()
    {
        return $this->hasMany(UserWelfareRecord::class, 'user_id', 'id');
    }

    public function carts()
    {
        return $this->hasMany(Cart::class, 'user_id', 'id');
    }
    public function children()
    {
        return $this->hasMany(User::class, 'parent_id', 'id');
    }

    public function moments()
    {
        return $this->hasMany(Moment::class, 'user_id', 'id');
    }

    public function momentLikes()
    {
        return $this->hasMany(MomentLike::class, 'user_id', 'id');
    }

    public function momentComments()
    {
        return $this->hasMany(MomentComment::class, 'user_id', 'id');
    }

      public function momentReplies()
    {
        return $this->hasMany(MomentReply::class, 'user_id', 'id');
    }

     public function attentions()
    {
        return $this->hasMany(UserAttention::class, 'user_id', 'id');
    }
    public function rewards()
    {
        return $this->hasMany(Reward::class, 'user_id', 'id');
    }

    public function activities()
    {
        return $this->hasMany(ActivityRecord::class, 'user_id', 'id');
    }
}
